package com.hlm.analysis;

import cn.hutool.core.util.ArrayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;

@Service
public class TempretureService {
    @Autowired Tempreture tempreture;
    @Autowired DataMapper dataMapper;
    private double a=1;
    private double b=1;
    private double c=10.0;
//    这个方法用来循环getparam
    public void goAnalysis(double[] results,double[] x,double[] y){
        //        设定所有初始值

//        double[] results=tempreture.get26920Intemp();
//        double[] x=tempreture.get26920WaterTemp();
//        double[] y=tempreture.get26920OutTemp();
        double learnRate=0.0001;
        System.out.println("results(intemp):"+ Arrays.toString(results));
        System.out.println("x(watertemp):"+Arrays.toString(x));
        System.out.println("y(outtemp):"+Arrays.toString(y));
//        循环调方法
        for(int i = 0 ; i <10000 ; i++){
//            System.out.println("循环第"+i+"次");
//            System.out.println("get之前的a："+a);
            getParam(a,b,c,results,x,y,learnRate);
            if(i==9999){
                System.out.println("get之后的a:"+a);
                System.out.println("get之后的b:"+b);
                System.out.println("get之后的c:"+c);
//                double loss=0.0;
//                System.out.println("误差：："+loss);
            }
        }
    }
    //    a供暖系数 b天气系数   c初始温度  results实际温度  x水温 y天气 learnRate 微调间隔
//    实现原理：每次将系数调整0.01  使得误差最小（在代码中体现为(result-预测的result)平方 求和最小）
//     误差导数：2*预测result  这时是每一条数据的。当求和时导数需要除以总条数
//     *********该方法需要循环使用
    public  void getParam(double a,double b,double c,double[] results,double[] x,double[] y,double learnRate){

        double sum =0;
//      循环微调a
        for (int j = 0; j < results.length; j++) {
            sum = sum + (a * x[j] + b * y[j] + c - results[j]) * x[j];
        }
//      调整的数值 即调整a与实际a的误差
        double updateValue = 2 * learnRate * sum / results.length;
//        System.out.println("a-updatvalue之前："+a);
//        System.out.println("updatevalue:"+updateValue);
//        System.out.println("a-update"+(a-updateValue));
        this.a = a - updateValue;
//        System.out.println("a======="+a);
//      循环微调b
        sum = 0;
        for (int j = 0; j < results.length; j++) {
            sum = sum + (a * x[j] + b * y[j]
                    + c - results[j]) * y[j];
        }
        updateValue = 2 * learnRate * sum / results.length;
        this.b = b- updateValue;
//        System.out.println("b:::::"+b);
//        sum =0;
//        for (int j = 0; j < results.length; j++) {
//            sum = sum + (a * x[j] + b * y[j] + c - results[j]) * y[j];
//        }
//        updateValue = 2 * learnRate * sum / results.length;
//        b= b - updateValue;
//        System.out.println("b"+b);
//       循环微调c
        sum =0;
        for (int j = 0; j < results.length; j++) {
            sum = sum + (a * x[j] + b * y[j] + c - results[j]) ;
        }
        updateValue = 200 * learnRate * sum / results.length;
        this.c = c - updateValue;
        sum =0;
//        System.out.println("c"+c);
    }
//  这个方法用来循环 terminal id 调用goAnalysis()
    public void getData(){
        int[] ids=dataMapper.getAllTerminalId();
        for(int i = 0 ; i <ids.length;i++){
            Integer id = ids[i] ;
            double[] results = dataMapper.getInTempById(id);
            double[] y = dataMapper.getOutTempById(id);
            double[] x = dataMapper.getWaterTempById(id);
            System.out.println("terminal_id::"+id);
//            只要有一组数据空 就放弃这组数据
            if(ArrayUtil.isEmpty(results) || ArrayUtil.isEmpty(x) || ArrayUtil.isEmpty(y)){
                continue;
            }
            goAnalysis(results,x,y);
//            把系数存起来
            dataMapper.saveMudulus(id,a+"",b+"",c+"");
        }
    }
}
